/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package modules.legislation;

import datatypes.Antenna;
import datatypes.RadiationPoint;
import java.util.Vector;
import javax.naming.directory.InvalidAttributesException;
import modules.dimensioning.LegislationInterface;
import modules.dimensioning.solution.Solution;
import modules.legislation.gridcoverage.CalculateSARValues;
import modules.legislation.gridcoverage.SamplingGrid;
import modules.legislation.law.Belgium;
import modules.legislation.law.CustomLaw;
import modules.legislation.law.LawInterface;
import modules.pathloss.CoverageAdapter;
import modules.pathloss.PathLossAdapter;
import tools.Log;
import tools.gis.shapewriter.Write2Shapefile;
import tools.math.MathTools;

/**
 *
 * @author Pieter Backaert
 */
public class LegislationAdapter implements LegislationInterface {

    private PathlossInterface instanceOfPathlossInterface;

    static final int SAMPLING_RESOLUTION=1000; //probeer later met 1000 en 10000
    private LawInterface law;
    private boolean INIT;

    private SamplingGrid sg; //bereken de SAMPLE VALUES
    private CalculateSARValues csv; //roep de feitelijke CHECK_LEGISLATION op

    private CoverageAdapter ca;
    private RadiationPoint[] rp;

    public LegislationAdapter(CoverageAdapter ca){
        instanceOfPathlossInterface = PathLossAdapter.getInstance();

        //edit B
        this.ca = ca;
        INIT = true;
        law = new Belgium(instanceOfPathlossInterface);
    }

    public LegislationAdapter(LawInterface law , CoverageAdapter ca){
        INIT = true;
        this.law = law;
        this.ca = ca;
    }

    public LegislationAdapter(double limit, CoverageAdapter ca){
        INIT = true;
        this.law = new CustomLaw(PathLossAdapter.getInstance() , limit);
        this.ca = ca;
    }


    /**
	 * Checks if a solution exceeds the maximum allowed SAR near the last-changed antenna
	 * Method clusters results so that all connected radiation exceeding points are merged
	 *
	 * @param s Solution to check
	 * @return Array of points where radiation is exceeded
	 */
	public RadiationPoint[] getRadiationExceedingPoints(Solution s) throws InvalidAttributesException {
        if(INIT){
            INIT=false;
            // build sampling grid
            sg = new SamplingGrid(s , SAMPLING_RESOLUTION, ca);
            sg.initSamplingGrid(); //enkel die antenna's die op 'active' staan worden meegerekend

            // for each sampled point : calculate SAR-value using legislation-laws
            csv = new CalculateSARValues(sg.getRadiationPointGrid() , sg.getAntennaGroupGrid()  ,   SAMPLING_RESOLUTION , law , ca);
            csv.calculateALL();
            rp = csv.returnRadiationPointArray();
            return rp;
        }
        else {
            //update waar nodig
            //sg.changeGridElements(s.getLatestChanges());

            Vector<Antenna> v = s.getLatestChanges();
            if(v==null || v.size()==0){
                return rp;
            }

            for(int i=0 ; i<v.size() ; i++){
                Antenna a = v.get(i);

                if(a.getActive())
                    sg.changeGridElementsForActiveAntenna(a);
                else
                    sg.changeGridElementsForInactiveAntenna(a);

                csv.setRadiationPointGrid( sg.getRadiationPointGrid() );
                csv.setAntennaGroupGrid( sg.getAntennaGroupGrid() );

                //check legislation-aanroep
                //die YMinIndex gaat anders zijn per antenna, daar staat deze lus hier (en kan het niet in SamplingGrid.java)
                csv.calculateForIndexBounds(sg.getYMinIndex() , sg.getYMaxIndex() , sg.getXMinIndex() , sg.getXMaxIndex() );
            }
            rp = csv.returnRadiationPointArray();
            return rp;
        }

        

    }

	/**
	 * Calculates the maximum allowable power for the antenna ,
     * Based upon :
     *      - Current range of the antenna [m]
     *      - Legislation-limit [V/m]
     *      - Antenna gain [dBi]
     *
	 *
	 * @param antenna Antenna to check
	 * @return Maximum power in dB = Power at which the antenna is operation [Watt]
	 */
	public double getMaximumAntennaPower(Antenna antenna)  {
        double EIRP=0;
        try {
            EIRP = Math.pow( ca.getRangeRadius(antenna)* law.giveELimit(antenna) , 2) / (30 * antenna.getGain());
        }
        catch(InvalidAttributesException e){}

        return MathTools.watt2dB(EIRP);
        


        // ONDERZOEK :
        //double freq = antenna.getFrequency();
    // conclusie : het zit hem in dit :
    // Radiated power [dBm] = Transmitter power [dBm] - cable loss [dB] + antenna gain[dBi]
     // Legal limit for radiated power (EiRP) for WLAN in Europe (except France) is 100mW (= +20dBm).

        // 0.
        // POWER wordt uitgedrukt in Waatt

        // 1.
        //Radiated power (power sent by the antenna at its direction of  maximum gain) can be easily computed (in dBm):
        //Radiated power [dBm] = Transmitter power [dBm] - cable loss [dB] + antenna gain[dBi]
        //return antenna.getPower()-antenna.getCable_attenuation()+antenna.getGain();

        //2.
        /**
         * Power
        Power is expressed in watts or milliwatts. Power can be expressed on a logarithmic scale relative to 1 mW, in dBm.  ('deci-Bell relative to one milliwat) . In that case,  the output is compared to one milliwatt.
        (1 dBm= 10*log10(P/ 0.001))
        (P in Watts)
    *   Usually, WLAN equipment has an output power of 15 dBm (about 30 mW)
    *    some equipment, have an output power of 100mW. Note: this is a DISadvantage if you want to make a long distance link within legal limits. See: Optimizing Link Power Within Legal Limits
        Conversion calculator  from Watts (W) to decibels "milliwatts" (dBm)  or visa versa. :
         */

        //3.
        /**
         * 10.3 Uitgestraald vermogen bij een antenne:
        * Effective isotropic radiated power (EIRP): het door de antenne uitgestraald vermogen: vermogen beschikbaar aan de ingang van de antenne + antennewinst + 2.15dB
         */ 
    }

	/**
	 * Calculates the maximum allowable distance for the antenna ,
     * REMINDER : this is TOTALLY DIFFERENT from antenna.getRange();
     *
     * Based upon :
     *      - EIRP [W]
     *          * Gain  [dBi]
     *          * Power [W]
     *      - Legislation-limit E [V/m]
     *
	 *
	 * @param antenna Antenna to check
	 * @return Maximum power in dB = Power at which the antenna is operation [Watt]
	 */
	public double getMaximumAntennaDistance(Antenna antenna){

        //LawInterface law = new Brussel();

        return  Math.sqrt(30 * (antenna.getGain()*antenna.getPower()) ) / (law.giveELimit(antenna));
    }

    public void printExceedingRadiationPoints(){
        if(rp==null || rp.length==0){
            Log.add(this, "LEGISLATION IS OK !!");
            return;
        }

        System.out.println();
        for(int i=0 ; i<rp.length ; i++){
            RadiationPoint rpi = rp[i];
            Log.add(this, "xco=" + rpi.getXCo() + "  yco=" + rpi.getYCo()  + "  SAR=" + rpi.getSAR() );
        }
        System.out.println();
    }

    public void writeRadiationPoints2shapefile(String name){
        if(rp==null || rp.length==0){
            Log.add(this, "nothing to write");
            return;
        }

        Write2Shapefile w2shp = new Write2Shapefile(ca);

        w2shp.writeRadiationPoints2shapefile(rp , name);

    }
    public void writeRadiationPoints2shapefile(){
        if(rp==null || rp.length==0){
            Log.add(this, "nothing to write");
            return;
        }

        Write2Shapefile w2shp = new Write2Shapefile(ca);

        w2shp.writeRadiationPoints2shapefile(rp , "");

    }
    public void setREBEGIN(boolean what){
        this.INIT = what;
    }
}
